home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / MacHacksBug / Python 1.5.2c1 / Mac / Lib / preferences.py < prev    next >
Encoding:
Python Source  |  2000-06-23  |  5.2 KB  |  220 lines

  1. #
  2. # General parser/loaders for preferences files and such
  3. #
  4. import Res
  5. import macfs
  6. import struct
  7. import MACFS
  8.  
  9. READ=1
  10. READWRITE=3
  11. Error = "Preferences.Error"
  12.  
  13. debug = 0
  14.  
  15. class NullLoader:
  16.     def __init__(self, data=None):
  17.         self.data = data
  18.         
  19.     def load(self):
  20.         if self.data is None:
  21.             raise Error, "No default given"
  22.         return self.data
  23.         
  24.     def save(self, data):
  25.         raise Error, "Cannot save to default value"
  26.         
  27.     def delete(self, deep=0):
  28.         if debug:
  29.             print 'Attempt to delete default value'
  30.         raise Error, "Cannot delete default value"
  31.         
  32. _defaultdefault = NullLoader()
  33.         
  34. class ResLoader:
  35.     def __init__(self, filename, resid, resnum=None, resname=None, default=_defaultdefault):
  36.         self.filename = filename
  37.         self.fss = macfs.FSSpec(self.filename)
  38.         self.resid = resid
  39.         self.resnum = resnum
  40.         self.resname = resname
  41.         self.default = default
  42.         self.data = None
  43.         
  44.     def load(self):
  45.         oldrh = Res.CurResFile()
  46.         try:
  47.             rh = Res.FSpOpenResFile(self.fss, READ)
  48.         except Res.Error:
  49.             self.data = self.default.load()
  50.             return self.data
  51.         try:
  52.             if self.resname:
  53.                 handle = Res.Get1NamedResource(self.resid, self.resname)
  54.             else:
  55.                 handle = Res.Get1Resource(self.resid, self.resnum)
  56.         except Res.Error:
  57.             self.data = self.default.load()
  58.         else:
  59.             if debug:
  60.                 print 'Loaded', (self.resid, self.resnum, self.resname), 'from', self.fss.as_pathname()
  61.             self.data = handle.data
  62.         Res.CloseResFile(rh)
  63.         Res.UseResFile(oldrh)
  64.         return self.data
  65.         
  66.     def save(self, data):
  67.         if self.data is None or self.data != data:
  68.             oldrh = Res.CurResFile()
  69.             rh = Res.FSpOpenResFile(self.fss, READWRITE)
  70.             try:
  71.                 handle = Res.Get1Resource(self.resid, self.resnum)
  72.             except Res.Error:
  73.                 handle = Res.Resource(data)
  74.                 handle.AddResource(self.resid, self.resnum, '')
  75.                 if debug:
  76.                     print 'Added', (self.resid, self.resnum), 'to', self.fss.as_pathname()
  77.             else:
  78.                 handle.data = data
  79.                 handle.ChangedResource()
  80.                 if debug:
  81.                     print 'Changed', (self.resid, self.resnum), 'in', self.fss.as_pathname()
  82.             Res.CloseResFile(rh)
  83.             Res.UseResFile(oldrh)
  84.             
  85.     def delete(self, deep=0):
  86.         if debug:
  87.             print 'Deleting in', self.fss.as_pathname(), `self.data`, deep
  88.         oldrh = Res.CurResFile()
  89.         rh = Res.FSpOpenResFile(self.fss, READWRITE)
  90.         try:
  91.             handle = Res.Get1Resource(self.resid, self.resnum)
  92.         except Res.Error:
  93.             if     deep:
  94.                 if debug: print 'deep in', self.default
  95.                 self.default.delete(1)
  96.         else:
  97.             handle.RemoveResource()
  98.             if debug:
  99.                 print 'Deleted', (self.resid, self.resnum), 'from', self.fss.as_pathname()
  100.         self.data = None
  101.         Res.CloseResFile(rh)
  102.         Res.UseResFile(oldrh)
  103.  
  104. class AnyResLoader:
  105.     def __init__(self, resid, resnum=None, resname=None, default=_defaultdefault):
  106.         self.resid = resid
  107.         self.resnum = resnum
  108.         self.resname = resname
  109.         self.default = default
  110.         self.data = None
  111.         
  112.     def load(self):
  113.         try:
  114.             if self.resname:
  115.                 handle = Res.GetNamedResource(self.resid, self.resname)
  116.             else:
  117.                 handle = Res.GetResource(self.resid, self.resnum)
  118.         except Res.Error:
  119.             self.data = self.default.load()
  120.         else:
  121.             self.data = handle.data
  122.         return self.data
  123.         
  124.     def save(self, data):
  125.         raise Error, "Cannot save AnyResLoader preferences"
  126.                     
  127.     def delete(self, deep=0):
  128.         raise Error, "Cannot delete AnyResLoader preferences"
  129.             
  130. class StructLoader:
  131.     def __init__(self, format, loader):
  132.         self.format = format
  133.         self.loader = loader
  134.         
  135.     def load(self):
  136.         data = self.loader.load()
  137.         return struct.unpack(self.format, data)
  138.         
  139.     def save(self, data):
  140.         data = apply(struct.pack, (self.format,)+data)
  141.         self.loader.save(data)
  142.         
  143.     def delete(self, deep=0):
  144.         self.loader.delete(deep)
  145.         
  146. class PstringLoader:
  147.     def __init__(self, loader):
  148.         self.loader = loader
  149.         
  150.     def load(self):
  151.         data = self.loader.load()
  152.         len = ord(data[0])
  153.         return data[1:1+len]
  154.         
  155.     def save(self, data):
  156.         if len(data) > 255:
  157.             raise Error, "String too big for pascal-style"
  158.         self.loader.save(chr(len(data))+data)
  159.         
  160.     def delete(self, deep=0):
  161.         self.loader.delete(deep)
  162.         
  163. class VersionLoader(StructLoader):
  164.     def load(self):
  165.         while 1:
  166.             data = self.loader.load()
  167.             if debug:
  168.                 print 'Versionloader:', `data`
  169.             try:
  170.                 rv = struct.unpack(self.format, data)
  171.                 rv = self.versioncheck(rv)
  172.                 return rv
  173.             except (struct.error, Error):
  174.                 self.delete(1)
  175.                 
  176.     def versioncheck(self, data):
  177.         return data
  178.         
  179. class StrListLoader:
  180.     def __init__(self, loader):
  181.         self.loader = loader
  182.         
  183.     def load(self):
  184.         data = self.loader.load()
  185.         num, = struct.unpack('h', data[:2])
  186.         data = data[2:]
  187.         rv = []
  188.         for i in range(num):
  189.             strlen = ord(data[0])
  190.             if strlen < 0: strlen = strlen + 256
  191.             str = data[1:strlen+1]
  192.             data = data[strlen+1:]
  193.             rv.append(str)
  194.         return rv
  195.  
  196.     def save(self, list):
  197.         rv = struct.pack('h', len(list))
  198.         for str in list:
  199.             rv = rv + chr(len(str)) + str
  200.         self.loader.save(rv)
  201.         
  202.     def delete(self, deep=0):
  203.         self.loader.delete(deep)
  204.  
  205. def preferencefile(filename, creator=None, type=None):
  206.     create = creator != None and type != None
  207.     vrefnum, dirid = macfs.FindFolder(MACFS.kOnSystemDisk, 'pref', create)
  208.     fss = macfs.FSSpec((vrefnum, dirid, ":Python:" + filename))
  209.     oldrf = Res.CurResFile()
  210.     if create:
  211.         try:
  212.             rh = Res.FSpOpenResFile(fss, READ)
  213.         except Res.Error:
  214.             Res.FSpCreateResFile(fss, creator, type, MACFS.smAllScripts)
  215.         else:
  216.             Res.CloseResFile(rh)
  217.             Res.UseResFile(oldrf)
  218.     return fss
  219.     
  220.